<?php
/*  ================================================================== *\
    (C) Copyright 2010 by Kenneth Downs

    This file is part of Triangulum 

    Triangulum is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    Triangulum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Triangulum; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor,
    Boston, MA  02110-1301  USA
    or visit http://www.gnu.org/licenses/gpl.html
\*  ================================================================== */
/**
 * Diff Test Suite Execution Program.
 * 
 * This is the comprehensive test management program for all
 * diff tests.  Diff tests ensure that Triangulum catches differences
 * between current database and spec and creates the proper commands
 * 
 * This program expects the "tests-diff" directory to be
 * in a subdirectory just below this actual program. 
 * 
 * Each test has a file in it called "desc.txt" that gives a short
 * description of the test.
 * 
 * At the beginning of the test run, this program drops all tables
 * out of the database "tritests".
 *
 * Then for each test:
 * - The programmer puts a dd file in subdirectory "sub1"
 * - The builder runs for sub1
 * - The programmer puts a dd file in subdirectory "sub2" that will
 *   have some additions
 * - The builder runs for sub2
 * - The diff debug report is captured from test-xxx/sub2/out and put into
 *   test-xxx/out as diff1
 * - The builder runs for sub2 again
 * - The diff debug report is again captured from test-xxx/sub2/out and
 *   put into test-xxx/out as diff2
 * - The file diff1, when judged to be correct, is put into test-xxx/compare
 *   as the standard for the test, as is diff2, which is expected to always
 *   depict an empty array
 * - The program compares all files in /test-xxx/compare to /test-xxx/out,
 *   and if they are all exactly the same the test passes
 * 
 * @package Andromeda
 * @author Ken Downs <kdowns@downsfam.net>
 */

main();

/**
 * 
 * @return unknown_type
 */
function main() {
    # HARDCODED 
    
    $dirs = scandir("./tests-diff");
    $prefix = '000.0';
    $pass   = 0;
    $failed = 0;
    $notest = 0;
    

    # Connect to main and drop/create database
    $dbx = 'dbname=postgres'
        .' host=localhost'
        .' user=postgres'
        .' password=postgres';
    $dbConn = pg_connect($dbx);
    echo "\n\n";
    echo "Dropping database tritests\n";
    pg_query($dbConn,"Drop database tritests");
    echo "Creating database tritests\n";
    pg_query($dbConn,"Create database tritests");
    pg_close($dbConn);
    $dbx = 'dbname=tritests'
        .' host=localhost'
        .' user=postgres'
        .' password=postgres';
    $dbConn = pg_connect($dbx);
    
    # Parms for calling triBuild
    $dbString = '--db-host=localhost --db-name=tritests '
        .' --db-user=postgres --db-passwd=postgres';
    
        
    # Now loop through each test
    foreach($dirs as $idx=>$dir) {
        if(substr($dir,0,1)=='.') continue;
        
        if(substr($dir,0,5)<>$prefix) {
            echo "\n\n";
        }
        $prefix = substr($dir,0,5);
        
        # make some subdirectories
        if(!is_dir("tests-diff/$dir/debug")) {
            mkdir("tests-diff/$dir/debug");
        }
        if(!is_dir("tests-diff/$dir/compare")) {
            mkdir("tests-diff/$dir/compare");
        }
        if(!is_dir("tests-diff/$dir/sub3")) {
            mkdir("tests-diff/$dir/sub3");
        }
        # Copy sub2 to sub3 always
        copy("tests-diff/$dir/sub2/sub2.dd.yaml"
            ,"tests-diff/$dir/sub3/sub3.dd.yaml");
            
        # Kill any previous results.  Otherwise some
        # failures will look like success because the files
        # from the previous run are still sitting there.
        if(file_exists("tests-diff/$dir/debug/diff1.txt"))
            unlink("tests-diff/$dir/debug/diff1.txt");
        if(file_exists("tests-diff/$dir/debug/diff1.txt"))
            unlink("tests-diff/$dir/debug/diff2.txt");
        if(file_exists("tests-diff/$dir/debug/diff1.txt"))
            unlink("tests-diff/$dir/debug/diff3.txt");
        
        
        # Purge the database to get a clean test
        pg_query($dbConn,"drop schema public cascade");
        pg_query($dbConn,"create schema public");
        
        
        # Run the test first time, copy over diff
        `php triBuild.php --yaml=tests-diff/$dir/sub1/sub1.dd.yaml $dbString > tests-diff/$dir/sub1/debug/log.txt`;
        copy("tests-diff/$dir/sub1/debug/diff.txt"
            ,"tests-diff/$dir/debug/diff1.txt");
        buildDatabase($dbConn,"tests-diff/$dir/sub1/out/build.postgres.sql");
        
        # Run the test second time, copy over diff
        `php triBuild.php --yaml=tests-diff/$dir/sub2/sub2.dd.yaml $dbString &> tests-diff/$dir/sub2/debug/log.txt`;
        copy("tests-diff/$dir/sub2/debug/diff.txt"
            ,"tests-diff/$dir/debug/diff2.txt");
        buildDatabase($dbConn,"tests-diff/$dir/sub2/out/build.postgres.sql");
        
        # Run yet a third time, expect an empty diff
        `php triBuild.php --yaml=tests-diff/$dir/sub3/sub3.dd.yaml $dbString &> tests-diff/$dir/sub3/debug/log.txt`;
        copy("tests-diff/$dir/sub3/debug/diff.txt"
            ,"tests-diff/$dir/debug/diff3.txt");
        
        # Get the description
        $desc = file_get_contents("tests-diff/$dir/desc.txt");
        while(substr($desc,-1)=="\n") {
            $desc = substr($desc,0,strlen($desc)-1);
        }
        
        # For making things line up
        $xdir = str_pad($dir,25);

        # Now read the files we are supposed to check, get
        # rid of '.' and '..'
        if(!is_dir("tests-diff/$dir/compare")) {
            echo "\n----   $xdir $desc";
            echo "\n  --   the compare/ subdirectory does not exist";
            $notest++;
            continue;
        }
        $files = scandir("tests-diff/$dir/compare");
        if(!is_array($files)) {
            echo "\n----   $xdir $desc";
            echo "\n  --   there are no files in the compare/ subdirectory";
            $notest++;
            continue;
        }
        array_shift($files);
        array_shift($files);
        foreach($files as $idx=>$file) {
            if(substr($file,-1)=='~') unset($files[$idx]);
        }
        if(count($files)==0) {
            echo "\n----   $xdir $desc";
            echo "\n  --   there are no files in the compare/ subdirectory";
            $notest++;
            continue;
        }
        
        # Initialize an empty list of failures and do the comparisons
        $fail = array();
        foreach($files as $file) {
            # KFD 5/14/09 general cleanup
            if(substr($file,0,1)=='.') continue;
            $compare = file_get_contents("tests-diff/$dir/compare/$file");
            $debug   = file_get_contents("tests-diff/$dir/debug/$file");
            
            if($compare<>$debug) {
                $fail[] = $file;
            }
        }
        
        if(count($fail)==0) {
            $pass++;
            echo "\nPASS   $xdir $desc";
        }
        else {
            $failed++;
            echo "\nFAIL** $xdir $desc\n";
            echo "\n  Files that failed:";
            foreach($fail as $onefail) {
                echo "\n    - $onefail";
            }
            echo "\n";
        }
    } 
    echo "\n\n";
    $pf = intval($pass) + intval($failed) + intval($notest);
    echo "\nPassed : ".str_pad(number_format($pass   ,0),6,' ',STR_PAD_LEFT);
    echo "\nNo Test: ".str_pad(number_format($notest ,0),6,' ',STR_PAD_LEFT);
    echo "\nFailed : ".str_pad(number_format($failed ,0),6,' ',STR_PAD_LEFT);
    echo "\nTOTAL  : ".str_pad(number_format($pf     ,0),6,' ',STR_PAD_LEFT);
    echo "\n\n";
}

function buildDatabase($dbConn,$filename) {
    $lines = explode(
        "-- COMMAND --"
       ,file_get_contents($filename)
    );
    $ok = 0;
    $todo=0;
    foreach($lines as $idx=>$oneline) {
        if(trim($oneline)=='') continue;
        $todo++;
        while(substr($oneline,-1)=="\n") 
            $oneline = rtrim($oneline,"\n");
        pg_query($dbConn,$oneline);
    } 
}
?>
